using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.IO;

namespace MacomberMap.Loader.Export.OneLines
{/// <summary>
    /// This class holds a DDL exporter
    /// </summary>
    public class MM_DDL_Exporter_Stream : StreamWriter
    {
        #region Variable Declarations
        /// <summary>The current indentation</summary>
        public int Indentation = 0;

        /// <summary>The name of the output stream</summary>
        public string Name;

        ///// <summary>The ESet corresponding to this file</summary>
        //public MM_DDL_Exporter_Stream ESet;
        #endregion

        #region Initialziation
        /// <summary>
        /// Initialize a new DDL exporter
        /// </summary>
        /// <param name="FileName"></param>
        public MM_DDL_Exporter_Stream(String FileName)
            : base(FileName, false, Encoding.ASCII)
        {
            this.Name = Path.GetFileNameWithoutExtension(FileName.Substring(0, FileName.LastIndexOf('_')));
            //if (FileName.Contains("_dset")) 
            //    this.ESet = new MM_DDL_Exporter_Stream(FileName.Replace("_dset", "_eset"), false);
        }

        /// <summary>
        /// Initialize a new DDL exporter
        /// </summary>
        /// <param name="FileName">The outgoing file name</param>
        /// <param name="Append">Whether the stream should be appended to</param>        
        public MM_DDL_Exporter_Stream(String FileName, bool Append)
            : base(FileName, Append, Encoding.ASCII)
        {
            this.Name = Path.GetFileNameWithoutExtension(FileName.Substring(0, FileName.LastIndexOf('_')));
            // if (FileName.Contains("_dset"))
            //    this.ESet = new MM_DDL_Exporter_Stream(FileName.Replace("_dset", "_eset"), Append);
        }
        #endregion

        #region Routines
        /// <summary>
        /// Write a blank line
        /// </summary>
        public override void WriteLine()
        {
            base.WriteLine(new String('\t', Indentation));
        }

        /// <summary>
        /// Write an attribute out to the DDL export
        /// </summary>
        /// <param name="Name">The name of the attribute</param>
        /// <param name="Value">The value of the attribute</param>
        public void WriteAttribute(String Name, String Value)
        {
            if (Name == "Value")
            {
                base.WriteLine(new String('\t', Indentation) + "localize \"" + Value + "\"");
                return;
            }
            if (Value == "false")
                base.Write(new String('\t', Indentation) + "not " + Name);
            else
                base.Write(new String('\t', Indentation) + Name);

            if (String.IsNullOrEmpty(Value))
                base.Write(" ");
            else if (Name == "localize")
                base.Write(" \"" + Value + "\"");
            else if (Name == "cam" || Name == "gab")
                base.Write(" \"" + Value + "\" ");
            else if (Name == "size" || Name == "position" || Name == "factor" || Name == "lo_declutter" || Name == "hi_declutter" || Name == "format" || Name == "width" || Name == "height" || Name == "justification")
                base.Write("(" + Value + ")");
            else if (Value == "left arrow" || Value == "up arrow" || Value == "right arrow" || Value == "down arrow")
                base.Write("(bitmap(\"" + Value + "\"))");
            else if (Name == "origin")
                base.Write("(" + Value.Replace(',', ' ') + ")");
            else if (Name == "point")
            {
                string[] splStr = Value.Split(',');
                base.WriteLine("(" + splStr[0] + " " + splStr[1] + ")");
                for (int a = 2; a < splStr.Length; a += 2)
                    WriteAttribute(Name, float.Parse(splStr[a]), float.Parse(splStr[a + 1]));
            }
            else if (Value != "true" && Value != "false")
                base.Write("(\"" + Value + "\") ");
            if (Indentation == 0)
                base.WriteLine(";");
            else
                base.WriteLine();
        }

        /// <summary>
        /// Write a text box
        /// </summary>
        /// <param name="Text"></param>
        /// <param name="Location"></param>
        /// <param name="Foreground"></param>
        /// <param name="Background"></param>
        /// <param name="Font"></param>
        /// <param name="FontSize"></param>
        /// <param name="Underline"></param>
        /// <param name="Bold"></param>
        /// <param name="Italics"></param>
        /// <param name="xLocked"></param>
        /// <param name="yLocked"></param>
        public void WriteText(String Text, Point Location, String Foreground, String Background, String Font, int FontSize, bool Underline, bool Bold, bool Italics, bool xLocked, bool yLocked)
        {
            WriteStartTag("text", "");
            WriteStartTag("gab", "");
            if (!String.IsNullOrEmpty(Foreground))
                WriteAttribute("foreground", "White");
            if (!String.IsNullOrEmpty(Background))
                WriteAttribute("background", Background);
            if (!String.IsNullOrEmpty(Font))
                WriteAttribute("font_family", Font);
            if (FontSize > 0)
                WriteAttribute("font_size", FontSize);
            if (Underline)
                WriteAttribute("font_underline");
            if (Italics && Bold)
                WriteAttribute("font_style", "Bold Italic");
            else if (Italics)
                WriteAttribute("font_style", "Italic");
            else if (Bold)
                WriteAttribute("font_style", "Bold");
            WriteEndTag();
            WriteAttribute("origin", Location.X, Location.Y);
            if (xLocked)
                WriteAttribute("xlocked");
            if (yLocked)
                WriteAttribute("ylocked");
            WriteAttribute("localize", Text);
            WriteEndTag();

        }

        /// <summary>
        /// Write text using an existing gab
        /// </summary>
        /// <param name="Text"></param>
        /// <param name="Gab"></param>
        /// <param name="Location"></param>
        /// <param name="xlocked"></param>
        /// <param name="ylocked"></param>
        public void WriteTextWithGab(String Text, String Gab, Point Location, bool xlocked, bool ylocked)
        {
            WriteStartTag("text", "");
            WriteAttribute("gab", Gab);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Location.X, Location.Y);
            if (xlocked)
                WriteAttribute("xlocked");
            if (ylocked)
                WriteAttribute("ylocked");
            WriteAttribute("localize", Text);
            WriteEndTag();
        }


        /// <summary>
        /// Write out the DDL header
        /// </summary>
        /// <param name="VersionInfo"></param>
        public void WriteHeader(String VersionInfo)
        {
            this.WriteLine();
            this.WriteAttribute("version", VersionInfo);
            this.Indentation++;
            this.WriteLine();
        }

        /// <summary>
        /// Write an attribute out to the DDL export
        /// </summary>
        /// <param name="Name">The name of the attribute</param>        
        public void WriteAttribute(String Name)
        {
            base.Write(new String('\t', Indentation) + Name + " ");
            if (Indentation == 0)
                base.WriteLine(";");
            else
                base.WriteLine();
        }

        /// <summary>
        /// Write an attribute out to the DDL export
        /// </summary>
        /// <param name="Name">The name of the attribute</param>
        /// <param name="Value">The value of the attribute</param>
        public void WriteAttribute(String Name, float Value)
        {
            base.Write(new String('\t', Indentation) + Name + "(" + Value + ") ");
            if (Indentation == 0)
                base.WriteLine(";");
            else
                base.WriteLine();
        }

        /// <summary>
        /// Write an attribute out to the DDL export
        /// </summary>
        /// <param name="Name">The name of the attribute</param>
        /// <param name="Value1">The value of the attribute</param>
        /// <param name="Value2">The second value of the attribute</param>
        public void WriteAttribute(String Name, float Value1, float Value2)
        {
            base.Write(new String('\t', Indentation) + Name + "(" + Value1 + " " + Value2 + ") ");
            if (Indentation == 0)
                base.WriteLine(";");
            else
                base.WriteLine();
        }

        /// <summary>
        /// Write an attribute out to the DDL export
        /// </summary>
        /// <param name="Name1">The name of the attribute</param>
        /// <param name="Name2">The second name of the attribute</param>
        /// <param name="Value">The value of the attribute</param>
        public void WriteAttribute(String Name1, String Name2, String Value)
        {
            base.WriteLine(new String('\t', Indentation) + Name1 + "(" + Name2 + " \"" + Value + "\")");
        }
        #endregion


        /// <summary>
        /// Write the starting tag of component
        /// </summary>
        /// <param name="Name"></param>
        /// <param name="Value"></param>
        public void WriteStartTag(string Name, string Value)
        {
            if (String.IsNullOrEmpty(Value))
                base.WriteLine("{0}{1} ", new String('\t', Indentation), Name);
            else
                base.WriteLine("{0}{1} \"{2}\"", new String('\t', Indentation), Name, Value);
            base.WriteLine(new String('\t', Indentation) + "(");
            Indentation++;
        }

        /// <summary>
        /// Write the end of a tag
        /// </summary>
        public void WriteEndTag()
        {
            Indentation--;
            if (Indentation == 1)
                base.WriteLine(new String('\t', Indentation) + ");");
            else
                base.WriteLine(new String('\t', Indentation) + ")");

        }

        /// <summary>
        /// Close and dispose of the stream writer
        /// </summary>
        public override void Close()
        {
            while (Indentation > 1)
                WriteEndTag();
            base.Close();
        }



        /// <summary>
        /// Write a rotated attribute
        /// </summary>
        /// <param name="Name"></param>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        /// <param name="Height"></param>
        /// <param name="Width"></param>
        /// <param name="Angle"></param>
        public void WriteRotatedAttribute(string Name, int X, int Y, int Width, int Height, int Angle)
        {
            if (Angle == 0)
                WriteAttribute(Name, X, Y);
            else if (Angle == 90)
                WriteAttribute(Name, Height - Y, Width - X);
            else if (Angle == 180)
                WriteAttribute(Name, Width - X, Height - Y);
            else if (Angle == 270)
                WriteAttribute(Name, Y, X);

        }

        /// <summary>
        /// Write out a composite key
        /// </summary>
        /// <param name="Keys"></param>
        public void WriteKey(params string[] Keys)
        {
            WriteStartTag("composite_key", "");
            foreach (string str in Keys)
            {
                string[] splStr = str.ToUpper().Split('=');
                WriteAttribute("record", splStr[0]);
                WriteAttribute("record_key", splStr[1]);
            }
            WriteEndTag();
        }

        /// <summary>
        /// Write out an old-style picture with associated records
        /// </summary>
        /// <param name="LabelName"></param>
        /// <param name="Location"></param>
        /// <param name="Keys"></param>
        public void WriteDataBoundPicture(string LabelName, Point Location, params string[] Keys)
        {
            WriteStartTag("picture", LabelName);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Location.X, Location.Y);
            WriteKey(Keys);
            WriteEndTag();
        }

        /// <summary>
        /// Write out an old-style picture with associated records
        /// </summary>
        /// <param name="SymbolName"></param>
        /// <param name="Location"></param>        
        public void WriteSymbol(string SymbolName, Point Location)
        {
            WriteStartTag("symbol", SymbolName);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Location.X, Location.Y);
            WriteEndTag();
        }

        /// <summary>
        /// Write out an old-style picture with associated records
        /// </summary>
        /// <param name="SymbolName"></param>
        /// <param name="Location"></param>  
        /// <param name="Offset"></param>
        public void WriteSymbol(string SymbolName, Point Location, Point Offset)
        {
            WriteStartTag("symbol", SymbolName);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Location.X + Offset.X, Location.Y + Offset.Y);
            WriteEndTag();
        }

        /// <summary>
        /// Write a single line, and if requested, an arrow on the receiving end
        /// </summary>
        /// <param name="Pt1">The start point</param>
        /// <param name="Pt2">The end point</param>
        /// <param name="ToArrow">Whether an arrow would be drawn</param>
        /// <param name="Gab">The name of the gab</param>
        public void WriteGraphicLine(Point Pt1, Point Pt2, bool ToArrow, string Gab)
        {
            WriteStartTag("polyline", "");
            WriteAttribute("gab", Gab);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Pt1.X, Pt1.Y);
            WriteAttribute("point", Pt1.X, Pt1.Y);
            WriteAttribute("point", Pt2.X - Pt1.X, Pt2.Y - Pt1.Y);
            WriteEndTag();
        }

        /// <summary>
        /// Write out a rectangle with specified gab
        /// </summary>
        /// <param name="Bounds"></param>
        /// <param name="Offset"></param>
        /// <param name="Gab"></param>
        public void WriteRectangle(Rectangle Bounds, Point Offset, string Gab)
        {
            WriteStartTag("rectangle", "");
            WriteAttribute("gab", Gab);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Bounds.Left + Offset.X, Bounds.Top + Offset.Y);
            WriteAttribute("width", Bounds.Width);
            WriteAttribute("height", Bounds.Height);
            WriteEndTag();

        }
    }
}